﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Reflection;
using System.ComponentModel;
using Grid.Extensions;

namespace LUC.Services
{
	public static class ViewAnyModel
	{
		public static Dictionary<Type, Type> MapComponents = new Dictionary<Type, Type>
		{
			{ typeof(string), typeof(TextBox) },
			{ typeof(int), typeof(NumericUpDown) },
			{ typeof(bool), typeof(CheckBox) },
			{ typeof(Font), typeof(FontTextBox) },
			{ typeof(Color),typeof(ColorTextBox) },
			{ typeof(DateTime), typeof(DateTimePicker) }
		};

		public static Dictionary<Type, Func<Control, BindingSource, PropertyInfo, Control>> MapBindingComponents =
			new Dictionary<Type, Func<Control, BindingSource, PropertyInfo, Control>>
		{
			{typeof(TextBox), (control, bs, p) =>
				{
					((TextBox)control).DataBindings.Add("Text", bs, p.Name,
						false, DataSourceUpdateMode.OnPropertyChanged);
					return control;
				}
			},
			{typeof(CheckBox), (control, bs, p) =>
				{
					((CheckBox)control).DataBindings.Add("Checked", bs, p.Name,
						false, DataSourceUpdateMode.OnPropertyChanged);
					return control;
				}
			},
			{typeof(FontTextBox), (control, bs, p) =>
				{
					((FontTextBox)control).DataBindings.Add("CurrentFont", bs, p.Name,
						false, DataSourceUpdateMode.OnPropertyChanged);
					return control;
				}
			},
			{typeof(ColorTextBox), (control, bs, p) =>
				{
					((ColorTextBox)control).DataBindings.Add("CurrentColor", bs, p.Name,
						false, DataSourceUpdateMode.OnPropertyChanged);
					return control;
				}
			},
			{typeof(NumericUpDown), (control, bs, p) =>
				{
					((NumericUpDown)control).DataBindings.Add("Value", bs, p.Name, 
						false, DataSourceUpdateMode.OnPropertyChanged);
					return control;
				}
			},
			{typeof(DateTimePicker), (control, bs, p) =>
				{
					((DateTimePicker)control).DataBindings.Add("Value", bs, p.Name, 
						false, DataSourceUpdateMode.OnPropertyChanged);
					return control;
				}
			}	

		};

		public static Dictionary<Type, Func<Control, PropertyInfo, Control>> CustomMapComponents =
			new Dictionary<Type, Func<Control, PropertyInfo, Control>>
		{
			{typeof(DateTimePicker), (control, p) =>
				{
					DateTimeFormatAttribute attr = p.GetCustomAttributes(
						typeof(DateTimeFormatAttribute), false).
						Cast<DateTimeFormatAttribute>().First();
					if (attr != null)
					{
						((DateTimePicker)control).Format = attr.Format;
						((DateTimePicker)control).CustomFormat = attr.CustomFormat;
					}
					else
					{
						((DateTimePicker)control).Format = DateTimePickerFormat.Short;	
					}
					return control;
				}	 
			},
			{typeof(NumericUpDown), (control, p) =>
				{
					NumericFormatAttribute attr = p.GetCustomAttributes(typeof(NumericFormatAttribute), false).
						Cast<NumericFormatAttribute>().FirstOrDefault();
					if (attr != null)
					{
						((NumericUpDown)control).Minimum = attr.MinValue;
						((NumericUpDown)control).Maximum = attr.MaxValue;
					}
					else
					{
						((NumericUpDown)control).Minimum = 0;
						((NumericUpDown)control).Maximum = 100;
					}
					return control;
				}
			
			}
		};
		
		public static void SetControlSource<T>(this Control gb, T data) where T:class
		{
			int num_row = 0;
			TableLayoutPanel tlp = new TableLayoutPanel();
			tlp.AutoSize = true;
			tlp.AutoSizeMode = AutoSizeMode.GrowAndShrink;
			
			tlp.Parent = gb;
			tlp.ColumnCount = 2;
			tlp.RowCount = typeof(T).GetProperties().Count(p=>
				p.GetCustomAttributes(typeof(DisplayNameAttribute), false).Length != 0);
			if (gb.GetType() == typeof(GroupBox))
			{
				tlp.Left = 5;
				tlp.Top = 20;

				((GroupBox)gb).AutoSize = true;
				((GroupBox)gb).AutoSizeMode = AutoSizeMode.GrowAndShrink;
			}
			else
				gb.AutoSize = true;
			Control control;
			BindingSource bs = new BindingSource();
			bs.Add(data);
			foreach (PropertyInfo p in typeof(T).GetProperties())
			{
				if ((p.GetCustomAttributes(typeof(DisplayNameAttribute),false)).Length != 0)
				{
					try
					{
						Type t = MapComponents[p.PropertyType];
						
						control = Activator.CreateInstance(t) as Control;
						if (CustomMapComponents.ContainsKey(t))
							control = CustomMapComponents[t](control, p);
						control.Name = p.Name;
						control.Parent = tlp;
						control = MapBindingComponents[t](control, bs, p);
						control.Dock = DockStyle.Fill;
						control.TabIndex = num_row;
						tlp.Controls.Add(control, 1, num_row);

						// Заголовок
						Label val_name = new Label
						{
							Text = ((DisplayNameAttribute)p.
								GetCustomAttributes(typeof(DisplayNameAttribute), false).First()).DisplayName,
							Parent = tlp,
							AutoSize = true,
							Anchor = (AnchorStyles)(AnchorStyles.Right | AnchorStyles.Top),
							Padding = new Padding(0, 3, 0, 0)
						};
						tlp.Controls.Add(val_name, 0, num_row++);
					}
					catch
					{
						throw new Exception("There no Component for view type '" + p.PropertyType + "', sorry.");
					}
				}
			}
		}		
	
		public static T ViewFormQuery<T>(string caption, T n_data) where T:class
		{
			T data = n_data;
			QueryForm qf = new QueryForm(caption);
			qf.SetControlSource(data);
			qf.Size = new Size(qf.Width, qf.Height + qf.b_ok.Height + 5);

			int cur_tab = typeof(T).GetProperties().Count(p =>
				p.GetCustomAttributes(typeof(DisplayNameAttribute), false).Length != 0);
			qf.b_ok.TabIndex = cur_tab++;
			qf.b_cancel.TabIndex = cur_tab;

			if (qf.ShowDialog() == DialogResult.OK)
				return data;
			else
				return null;
		}
	}

}
